use crate::{CsvOpts, OutputFormat, OutputTrait};
use csv::Reader;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "PascalCase")]
struct Player {
    name: String,
    position: String,
    #[serde(rename = "DOB")]
    dob: String,
    nationality: String,
    #[serde(rename = "Kit Number")]
    kit: u8,
}

// 新增一个包装结构体
#[derive(Debug, Serialize, Deserialize)]
struct PlayersWrapper {
    players: Vec<Player>,
}

pub fn handle_csv(opts: CsvOpts) -> anyhow::Result<()> {
    let mut reader = Reader::from_path(&opts.input)?;
    let mut ret = Vec::new();

    // let headers = reader.headers()?.clone();
    // for result in reader.records() {
    //     let record = result?;

    //     let json_value = headers.iter().zip(record.iter()).collect::<Value>();
    //     ret.push(json_value);
    // }

    for result in reader.deserialize() {
        let player: Player = result?;
        ret.push(player);
    }
    let output: String = opts.get_output_formatted();

    match &opts.format {
        OutputFormat::JSON => {
            let content = serde_json::to_string_pretty(&ret)?;
            write_to_file(&output, &content)?;
        }
        OutputFormat::XML => {
            let content = serde_xml_rs::to_string(&ret)?;
            write_to_file(&output, &content)?;
        }
        OutputFormat::CSV => {
            let mut wtr = csv::Writer::from_path(&output)?;
            for player in &ret {
                wtr.serialize(player)?;
            }
            wtr.flush()?;
        }
        OutputFormat::YAML => {
            let content = serde_yaml::to_string(&ret)?;
            write_to_file(&output, &content)?;
        }
        OutputFormat::TOML => {
            let wrapper = PlayersWrapper {
                players: ret.clone(),
            };
            let content = toml::to_string(&wrapper)?;
            write_to_file(&output, &content)?;
        }
    };

    println!("********** {} records processed. **********", &ret.len());
    Ok(())
}

fn write_to_file(output: &str, data: &str) -> anyhow::Result<()> {
    std::fs::write(output, data)?;
    Ok(())
}
